/*
 *  
    Copyright (C) 2008  Nathaniel Waisbrot

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package termint.gui;

import java.util.Arrays;

import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;

import termint.gui.graphics.TilesTextColor;
import termint.gui.vt.VT320;
import termint.gui.vt.VTChangeEvent;
import termint.gui.vt.VTChangeListener;
import termint.gui.vt.VTElement;

/**
 * @author Nathaniel Waisbrot
 * This is a SWT wrapper around the VT320 class.  Add it as a widget, then insert raw terminal data
 * into it.  It parses the escape codes and displays the image.
 */
public class SWTTextColor extends SWTTerm implements VTChangeListener {
	private static final int defaultFontSize = 12;
	TilesTextColor tiles;
	boolean[] needsUpdate;

	/**
	 * Create a new terminal display using the given terminal.  Display at the given font size.
	 * @param parent the widget containing this widget
	 * @param vt the VT320 backing this display
	 * @param fontSize the font to use when displaying the VT
	 */
	public SWTTextColor(Composite parent, VT320 vt, int fontSize) {
		super(parent, vt);
		moreSetup(fontSize);
	}
	
	/**
	 * Create a terminal display with the default font size.
	 * @param parent
	 * @param vt
	 */
	public SWTTextColor(Composite parent, VT320 vt) {
		super(parent, vt);
		moreSetup(defaultFontSize);
	}
	
	/**
	 * Create a terminal display with the given parent
	 * @param parent
	 */
	public SWTTextColor(Composite parent) {
		super(parent);
		moreSetup(defaultFontSize);
	}
	
	/**
	 * @see org.eclipse.swt.widgets.Widget#dispose()
	 */
	@Override
	public void dispose() {
		super.dispose();
		tiles.dispose();
	}
	
	/**
	 * Additional setup, common to all constructors
	 * @param fontSize font size to use when displaying text
	 */
	private void moreSetup(int fontSize) {
		tiles = new TilesTextColor(getDisplay(), fontSize);
		this.setSize(getSize());
		needsUpdate = new boolean[vt.height];
		Arrays.fill(this.needsUpdate, true);
	}
		
	
	/**
	 * @see org.eclipse.swt.widgets.Control#getSize()
	 */
	@Override
	public Point getSize() {
		return new Point(convertWidth(vt.width), convertHeight(vt.height));
	}
	
	/**
	 * used to handle self-painting
	 * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
	 */
	public void paintControl(PaintEvent e) {
		int x = vt.getCursorColumn();
		int y = vt.getCursorRow();
		for (int h = 0; h < vt.height; h++) {
			if (needsUpdate[h]) {
			for (int w = 0; w < vt.width; w++) {
				VTElement elt = vt.elementAt(w, h);
				Image i = tiles.getImage(elt);
				e.gc.drawImage(i, convertWidth(w), convertHeight(h));
			}
			}
		}
		e.gc.drawImage(tiles.getCursor(), convertWidth(x), convertHeight(y));
	}

	/**
	 * @see VTChangeListener#VTChanged(VTChangeEvent)
	 */
	public void VTChanged(VTChangeEvent event) {
		assert event.getChanges().length == needsUpdate.length;
		for (int i = 0; i < needsUpdate.length; i++) {
			needsUpdate[i] = needsUpdate[i] | event.getChanges()[i];
		}
	}
	
	/**
	 * Convert a width in VT characters into a width in SWT's pixels
	 * @param w width in VT chars
	 * @return width in pixels
	 */
	public int convertWidth(int w) {
		return leftMargin + tiles.getTileWidth() * w;
	}
	
	/**
	 * Convert a height in VT characters into a width in SWT's pixels
	 * @param h height in VT chars
	 * @return height in pixels
	 */
	public int convertHeight(int h) {
		return topMargin + tiles.getTileHeight() * h;
	}

	@Override
	public VTElement tileAtPoint(Point p) {
		// TODO Auto-generated method stub
		throw new UnsupportedOperationException("tileAtPoint");
	}
}
